package interfacedesign.config;

import ch.qos.logback.core.util.TimeUtil;
import interfacedesign.bean.TokenInfo;
import interfacedesign.util.ApiUtil;
import interfacedesign.util.NotRepeatSubmit;
import interfacedesign.util.RedisDB;
import org.springframework.stereotype.Component;
import org.springframework.util.Assert;
import org.springframework.util.StringUtils;
import org.springframework.web.servlet.handler.HandlerInterceptorAdapter;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.concurrent.TimeUnit;

/**
 * @ClassName TokenInterceptor
 * @Description: TODO
 * @Author jiajun
 * @Date 2021/5/14 
 * @Version V1.0
 **/
@Component
public class TokenInterceptor extends HandlerInterceptorAdapter  {
    /**
     * 访问目标方法前做校验
     * @param request
     * @param response
     * @param handler
     * @return
     * @throws Exception
     */
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
            throws Exception {

        // 1、获取token、timeStamp、nonce(随机字符串)、sign
        String token = request.getParameter("token");
        String timeStamp = request.getParameter("timeStamp");
        String nonce = request.getParameter("nonce");
        String sign = request.getParameter("sign");
        Assert.isTrue(!StringUtils.isEmpty(token) && !StringUtils.isEmpty(timeStamp) && !StringUtils.isEmpty(sign), "参数错误");
        // 2、获取超时时间
        NotRepeatSubmit notRepeatSubmit = ApiUtil.getNotRepeatSubmit(handler);
        long expireTime = notRepeatSubmit == null ? 5 * 60 * 1000 : notRepeatSubmit.value();

        // 3、获取请求时间间隔
        long requestInterval = System.currentTimeMillis() - Long.parseLong(timeStamp);
        Assert.isTrue(requestInterval < expireTime, "请求超时，请重新请求");

        // 4、校验token是否存在
        TokenInfo tokenInfo = RedisDB.get(token);
        Assert.notNull(tokenInfo, "token错误");

        // 5. 拒绝重复调用(第一次访问时存储，过期时间和请求超时时间保持一致), 只有标注不允许重复提交注解的才会校验
        if (notRepeatSubmit != null) {
            boolean exits = RedisDB.hasKey(sign);
            Assert.isTrue(!exits, "请勿重复提交！");
            RedisDB.put(sign, 0, expireTime);
        }

        return super.preHandle(request, response, handler);
    }
}
